<?php
/**
 * Created by PhpStorm.
 * User: wangjie
 * Date: 2021/01/22
 * Time: 17:49
 */
namespace App\Api\Controllers\YinSheng;


use Illuminate\Support\Facades\Log;
use App\Api\Controllers\BaseController as BBaseController;

class BaseController extends BBaseController
{
    protected $_charset = 'UTF-8'; //商户网站使用的编码格式
    protected $_version = '3.5'; //接口版本
    protected $_sign_type = 'RSA'; //签名类型

    protected $_url = 'https://qrcode.ysepay.com/gateway.do'; //正式环境


    /**
     * post发送请求
     *
     * @param string $url 请求地址
     * @param array $myParams 请求数据
     * @param string $public_key 验签公钥地址
     * @param string $response_name 返回数据key值
     * @return array 1-成功;2-失败
     */
    function post_url($url, $myParams, $public_key, $response_name)
    {
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($myParams));
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        $response = curl_exec($ch);
        if (curl_errno($ch)) {
            return [
                'status' => 2,
                'message' => $ch
            ];
        } else {
            $response = json_decode($response, true);
            Log::info('银盛支付-请求result');
            Log::info($response);
            if($response['sign'] != null){
                $sign = $response['sign'];
                Log::info('银盛支付-返回签名');
                Log::info($sign);
                $data = json_encode($response[$response_name], JSON_UNESCAPED_UNICODE);
                /* 验证签名 仅作基础验证*/
//                if ($this->sign_check($sign, $data, $public_key) == true) {
                    Log::info('银盛支付-验证签名成功-返回数据');
                    Log::info($response[$response_name]);
                    return [
                        'status' => 1,
                        'message' => '成功',
                        'data' => $response[$response_name]
                    ];
//                } else {
//                    return [
//                        'status' => 2,
//                        'message' => '验证签名失败'
//                    ];
//                }
            } else {
                return [
                    'status' => 2,
                    'message' => 'unknown error'
                ];
            }
        }
    }


    /**
     * 验签转明码
     *
     * @param string $sign 签名
     * @param object $data 数据
     * @param string $public_key 验签公钥地址
     * @return int
     */
    public function sign_check($sign, $data, $public_key)
    {
        $certificateCAcerContent = file_get_contents($public_key);
        $certificateCApemContent = '-----BEGIN CERTIFICATE-----' . PHP_EOL . chunk_split(base64_encode($certificateCAcerContent), 64, PHP_EOL) . '-----END CERTIFICATE-----' . PHP_EOL;
        // 签名验证
        $success = openssl_verify($data, base64_decode($sign), openssl_get_publickey($certificateCApemContent), OPENSSL_ALGO_SHA1);

        return $success;
    }


    /**
     * 日期转字符
     * 输入参数：yyyy-MM-dd HH:mm:ss
     * 输出参数：yyyyMMddHHmmss
     */
    function datetime2string($datetime)
    {
        return preg_replace('/\-*\:*\s*/', '', $datetime);
    }


    /**
     * 数组按键排序
     * @param array $paramArr
     * @return mixed
     */
    public function keySort($paramArr)
    {
        ksort($paramArr);

        return $paramArr;
    }


    /**
     * 拼接参数
     * @param array $data
     * @return string
     */
    public function SplicingString($data)
    {
        $signStr = "";
        foreach ($data as $key => $val) {
            $signStr .= $key . '=' . $val . '&';
        }
        $signStr = rtrim($signStr, '&');

        return $signStr;
    }


    /**
     * 签名加密
     *
     * @param string $data 排序、连接后数据
     * @param string $private_key 商户私钥
     * @param string $pfx_password 商户私钥证书密码
     * @return array
     */
    function pay_sign_encrypt($data, $private_key, $pfx_password)
    {
        $return = array(
            'success' => 0,
            'msg' => '',
            'check' => ''
        );

        $pkcs12 = file_get_contents($private_key);
        if (openssl_pkcs12_read($pkcs12, $certs, $pfx_password)) {
            Log::info('证书,密码,正确读取');
            $privateKey = $certs['pkey'];
            $publicKey = $certs['cert'];
            $signedMsg = "";
//            Log::info("加密密钥" . $privateKey);
            if (openssl_sign($data, $signedMsg, $privateKey, OPENSSL_ALGO_SHA1)) {
                Log::info('签名正确生成');
                $return['success'] = 1;
                $return['check'] = base64_encode($signedMsg);
                $return['msg'] = base64_encode($data);
            }
            //check
        } else {
            Log::info('证书,密码,读取失败');
        }

        return $return;
    }


    /**
     * 二维码支付 请求      1-成功 2-失败
     * @param $myParams
     * @param $public_key
     * @return array
     */
    public function sendQrCurlRequest($myParams, $public_key, $ways_source = '')
    {
        $ch = curl_init($this->_url);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($myParams));
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        $response = curl_exec($ch);
        Log::info('银盛支付-二维码支付-原始返回');
        Log::info($response);
        if (curl_errno($ch)) {
            return [
                'status' => 2,
                'data' => $ch
            ];
        } else {
            $response = json_decode($response, true);
            Log::info('银盛支付-二维码支付-原始返回');
            Log::info($response);

            $sign = $response['sign'];
            if ($ways_source == 'weixin'){
                $data = json_encode($response['ysepay_online_weixin_pay_response'], 320);
            }else{
                $data = json_encode($response['ysepay_online_qrcodepay_response'], 320);
            }
            Log::info('银盛支付-二维码支付-返回22');
            Log::info($data);
            /* 验证签名 仅作基础验证*/
            if ($this->sign_check($sign, $data, $public_key) == true) {
                return [
                    'status' => 1,
                    'message' => '成功',
                    'data' => $data
                ];
            } else {
                return [
                    'status' => 2,
                    'message' => '验证签名失败'
                ];
            }
        }

    }


    /**
     * 错误信息
     * @param string $code 错误码
     * @return string
     */
    public function msgByErrorCode($code)
    {
        switch ($code)
        {
            case '20000':
                return 'Service Currently Unavailable';
                break;
            case 'aop.unsupport-operation':
                return '不支持的操作';
                break;
            case 'aop.unknow-error':
                return '系统繁忙';
                break;
            case 'isp.unknow-error':
                return '系统繁忙';
                break;
            case '20001':
                return 'Insufficient Token Permissions';
                break;
            case 'aop.invalid-auth-token':
                return '无效的访问令牌';
                break;
            case 'aop.auth-token-time-out':
                return '访问令牌已过期';
                break;
            case '40001':
                return 'Missing Required Arguments';
                break;
            case 'isv.missing-method':
                return '缺少方法名参数';
                break;
            case 'isv.missing-signature':
                return '缺少签名参数';
                break;
            case 'isv.missing-signature-type':
                return '缺少签名类型参数';
                break;
            case 'isv.missing-signature-key':
                return '缺少签名配置';
                break;
            case 'isv.missing-partner-id':
                return '缺少 partner_id 参数';
                break;
            case 'isv.missing-timestamp':
                return '缺少时间戳参数';
                break;
            case 'isv.missing-version':
                return '缺少版本参数';
                break;
            case '40002':
                return 'Invalid Arguments';
                break;
            case 'isv.invalid-parameter':
                return '参数无效，格式不对、非法值、越界等';
                break;
            case 'isv.upload-fail':
                return '文件上传失败';
                break;
            case 'isv.invalid-file-extension':
                return '文件扩展名无效';
                break;
            case 'isv.invalid-file-size':
                return '文件大小无效';
                break;
            case 'isv.invalid-platform':
                return '无效的平台来源';
                break;
            case 'isv.invalid-method':
                return '不存在的方法名';
                break;
            case 'isv.invalid-format':
                return '无效数据格式';
                break;
            case 'isv.invalid-signature-type':
                return '无效签名类型';
                break;
            case 'isv.invalid-signature':
                return '无效签名';
                break;
            case 'isv.invalid-partner-id':
                return '无效的 partner_id 参数';
                break;
            case 'isv.invalid-timestamp':
                return '非法的时间戳参数';
                break;
            case 'isv.invalid-version':
                return '非法的版本参数';
                break;
            case 'isv.unsupported-version':
                return '不支持的版本号';
                break;
            case 'isv.invalid-encoding':
                return '编码错误';
                break;
            case 'isv.invalid-charset':
                return '字符集错误';
                break;
            case 'isv.invalid-digest-type':
                return '摘要类型错误';
                break;
            case 'isv.invalid-digest':
                return '摘要错误';
                break;
            case 'isv.invalid-app-method':
                return '应用不包含此方法名';
                break;
            case 'isv.illegal-json':
                return '不正确的 JSON 格式';
                break;
            case 'isv.illegal-card-no':
                return '不正确的卡号';
                break;
            case '40005':
                return 'Call Limited';
                break;
            case 'isv.app-call-limited':
                return '应用调用次数超限，包含调用频率超限';
                break;
            case 'isv.method-call-limited':
                return 'API 调用次数超限，包含调用频率超限';
                break;
            case '40006':
                return 'Insufficient Permissions';
                break;
            case 'isv.insufficient-isv-permissions':
                return 'ISV 权限不足';
                break;
            case 'isv.insufficient-user-permissions':
                return '用户权限不足';
                break;
            case '40003':
                return 'Invalid Business Arguments';
                break;
            case '40004':
                return 'Business Failed';
                break;
            case '50000':
                return 'Business In Process';
                break;
            default:
                return '未知错误码';
        }
    }













    /**
     * curl POST
     *
     * @param   string  url
     * @param   array   数据
     * @param   int     请求超时时间
     * @param   bool    HTTPS时是否进行严格认证
     * @return  string
     */
    function curlPost($url, $data = array(), $timeout = 30, $CA = true)
    {
        $cacert = ROOT_PATH . '/Epay/cacert.pem'; //CA根证书
        $SSL = substr($url, 0, 8) == "https://" ? true : false;

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout - 2);
//        if ($SSL && $CA) {
//            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);   // 只信任CA颁布的证书
//            curl_setopt($ch, CURLOPT_CAINFO, $cacert); // CA根证书（用来验证的网站证书是否是CA颁布）
//            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); // 检查证书中是否设置域名，并且是否与提供的主机名匹配
//        } else if ($SSL && !$CA) {
//            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 信任任何证书
//            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1); // 检查证书中是否设置域名
//        }
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:')); //避免data数据过长问题
        curl_setopt($ch, CURLOPT_POST, true);
//        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); //data with URLEncode

        $ret = curl_exec($ch);
//        var_dump(curl_error($ch));  //查看报错信息

        curl_close($ch);
        return $ret;
    }


    /**
     * 签名加密
     * @param array $input
     * @return mixed
     */
    public function sign_encrypt($input)
    {
        $return = [
            'success' => 0,
            'msg' => '',
            'check' => ''
        ];
        $pkcs12 = file_get_contents($this->pfxpath); //私钥
        if (openssl_pkcs12_read($pkcs12, $certs, $this->pfxpassword)) {
            $privateKey = $certs['pkey'];
            $publicKey = $certs['cert'];
            $signedMsg = "";
            if (openssl_sign($input['data'], $signedMsg, $privateKey, OPENSSL_ALGO_SHA1)) {
                $return['success'] = 1;
                $return['check'] = base64_encode($signedMsg);
                $return['msg'] = base64_encode($input['data']);
            }
        }

        return $return;
    }


    //签名
    public function sign($data)
    {
        ksort($data);
        $signStr = "";
        foreach ($data as $key => $val) {
            $signStr .= $key . '=' . $val . '&';
        }
        $signStr = trim($signStr, '&');
        $sign = $this->sign_encrypt(array('data' => $signStr));
        return trim($sign['check']);
    }


    //验签
    public function sign_verify($data)
    {
        //返回的数据处理
        $sign = trim($data['sign']);
        unset($data['sign']);
        ksort($data);
        $url = "";
        foreach ($data as $key => $val) {
            /* 验证签名 */
            if ($val) $url .= $key . '=' . $val . '&';
        }
        $str = trim($url, '&');
        if ($this->sign_check($sign, $str) != true) {
            return false;
        } else {
            return true;
        }
    }


    public function getBankType($name)
    {
        $arr = [
            '1041000' => '中国银行',
            '1031000' => '中国农业银行',
            '1021000' => '中国工商银行',
            '1051000' => '中国建设银行',
            '3012900' => '交通银行',

            '3085840' => '招商银行',
            '3051000' => '中国民生银行',
            '3093910' => '兴业银行',
            '3102900' => '浦发银行', // 上海浦东发展银行
//            '3065810' => '广东发展银行',

            '3021000' => '中信银行',
            '3031000' => '光大银行',
            '4031000' => '中国邮政储蓄银行',
            '3071000' => '平安银行',
//            '3131000' => '北京银行',

//            '3133010' => '南京银行',
//            '3133320' => '宁波银行',
//            '3222900' => '上海农村商业银行',
//            '5021000' => '东亚银行',
            '3041000' => '华夏银行',
        ];

        foreach ($arr as $k => $v) {
            if (strpos($v, $name) !== false || strpos($name, $v) !== false) {
                if ($v == '浦发银行') {
                    $v = '上海浦东发展银行';
                }
                return [$k, $v];
            }
        }
    }


    /**
     * DES加密方法
     * @param $data 传入需要加密的证件号码
     * @param $key key为商户号前八位.不足八位的需在商户号前补空格
     * @return string 返回加密后的字符串
     */
    function ECBEncrypt($data, $key)
    {
        $encrypted = openssl_encrypt($data, 'DES-ECB', $key, 1);
        return base64_encode($encrypted);
    }


    /**
     * DES解密方法
     * @param $data 传入需要解密的字符串
     * @param $key key为商户号前八位.不足八位的需在商户号前补空格
     * @return string 返回解密后的证件号码
     */
    function doECBDecrypt($data, $key)
    {
        $encrypted = base64_decode($data);
        $decrypted = openssl_decrypt($encrypted, 'DES-ECB', $key, 1);
        return $decrypted;
    }


    /**
     * 数组转字符串
     */
    function arrayToString($arr)
    {
        if (is_array($arr)) {
            return implode(',', array_map('arrayToString', $arr));
        }
        return $arr;
    }


}
